﻿#include "ulabel.h"

#include <QPainter>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QSvgRenderer>
#include <QTextDocument>
#include <QPainterPath>
#include <QIcon>

class ULabelPrivate
{
public:
    ULabelPrivate(ULabel* q) : q_ptr(q) {}
    ~ULabelPrivate() {}
private:
    Q_DECLARE_PUBLIC(ULabel)
    Q_DISABLE_COPY(ULabelPrivate)
    ULabel* const q_ptr = nullptr;
    QPixmap pixmap;
    QSvgRenderer svgRenderer;
    QString iconPath = QString();
    QColor textColor = QColor();
    Qt::TextElideMode mode = Qt::TextElideMode::ElideMiddle;
    QIcon icon;
    int radius = 0;
};

ULabel::ULabel(QWidget* parent) : QLabel(parent)
    , d_ptr(new ULabelPrivate(this))
{
}

ULabel::ULabel(const QString &text, QWidget* parent) : QLabel(text, parent)
    , d_ptr(new ULabelPrivate(this))
{
}

ULabel::~ULabel()
{
}

void ULabel::setRadius(int radius)
{
    Q_D(ULabel);
    if (d->radius != radius)
    {
        d->radius = radius;
        update();
    }
}

void ULabel::setTextSize(int size)
{
    QFont fnt = font();
    fnt.setPixelSize(size);
    setFont(fnt);
}

void ULabel::setFontFamily(const QString &family)
{
    QFont fnt = font();
    fnt.setFamily(family);
    setFont(fnt);
}

void ULabel::setFontWeight(int weight)
{
    QFont fnt = font();
    fnt.setWeight(weight);
    setFont(fnt);
}

void ULabel::setFontColor(const QColor &color)
{
    Q_D(ULabel);
    if (d->textColor != color)
    {
        d->textColor = color;
        update();
    }
}

QColor ULabel::fontColor() const
{
    Q_D(const ULabel);
    return d->textColor;
}

void ULabel::setIcon(const QIcon &icon)
{
    Q_D(ULabel);

    d->icon = icon;
    update();
}

QIcon ULabel::icon()
{
    Q_D(ULabel);
    return d->icon;
}

void ULabel::setLabelPixmap(const QPixmap &pixmap)
{
    Q_D(ULabel);
#if (QT_VERSION >= QT_VERSION_CHECK(5,15,0))
    if (d->pixmap != pixmap)
#endif
    {
        d->pixmap = pixmap;
        update();
    }
}

void ULabel::setSvgPicture(const QString &iconPath)
{
    Q_D(ULabel);
    if (d->iconPath != iconPath)
    {
        d->iconPath = iconPath;
        update();
    }
}

void ULabel::setElideMode(Qt::TextElideMode mode)
{
    Q_D(ULabel);
    if (d->mode != mode)
    {
        d->mode = mode;
        update();
    }
}

QPixmap ULabel::labelPixmap()
{
    Q_D(ULabel);
    return d->pixmap;
}

void ULabel::mousePressEvent(QMouseEvent* event)
{
    if (event->button() == Qt::LeftButton)
    {
        emit pressed();
    }
    QLabel::mousePressEvent(event);
}

void ULabel::mouseReleaseEvent(QMouseEvent* event)
{
    if (event->button() == Qt::LeftButton)
    {
        emit released();
        emit clicked();
    }
    QLabel::mouseReleaseEvent(event);
}

void ULabel::paintEvent(QPaintEvent* event)
{
    Q_D(ULabel);
    QPainter painter(this);
    QRect rect = this->rect();
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);

    painter.setOpacity(isEnabled() ? 1.0 : 0.4);
    QColor color = d->textColor.isValid() ? d->textColor : palette().color(QPalette::WindowText);
    painter.setPen(color);

    if (!d->pixmap.isNull())
    {
        QPainterPath path;
        path.addRoundedRect(this->rect(), d->radius, d->radius);
        painter.setClipPath(path);
        painter.drawPixmap(this->rect(), d->pixmap);
    }

    if (!d->icon.isNull())
    {
        QPainterPath path;
        path.addRoundedRect(this->rect(), d->radius, d->radius);
        painter.setClipPath(path);
        QIcon::Mode mode = isEnabled() ? QIcon::Normal : QIcon::Disabled;
        d->icon.paint(&painter, this->rect(), Qt::AlignCenter, mode);
    }

    if (!d->iconPath.isEmpty())
    {
        d->svgRenderer.load(d->iconPath);
#if (QT_VERSION >= QT_VERSION_CHECK(5,15,0))
        d->svgRenderer.setAspectRatioMode(Qt::KeepAspectRatio);
#endif
        QSize size = d->svgRenderer.defaultSize();
        int pixWidth = (size.width() > rect.width()) ? rect.width() : size.width();
        int pixHeight = (size.height() > rect.height()) ? rect.height() : size.height();
        QRect pixRect = QRect(rect.center().x() - pixWidth / 2, rect.center().y() - pixHeight / 2, pixWidth, pixHeight);
        QPainterPath path;
        path.addRoundedRect(pixRect, d->radius, d->radius);
        painter.setClipPath(path);
        d->svgRenderer.render(&painter, pixRect);
    }

    if (Qt::mightBeRichText(this->text()))
    {
        QLabel::paintEvent(event);
        return;
    }

    if (this->text().isEmpty())
    {
        return;
    }
    painter.setFont(font());
    rect.setX(indent());
    if (wordWrap())
    {
        painter.drawText(rect, static_cast<int>(alignment()) | Qt::TextWordWrap, this->text());
    }
    else
    {
        QFontMetrics fm(font());
        QString text = fm.elidedText(this->text(), d->mode, width());
        painter.drawText(rect, static_cast<int>(alignment()) | Qt::TextSingleLine, text);
    }
}
